module Manager {

    export class GameManager {
        private static _init: GameManager = null;

        public static dropTypes: string[] = ["drop_food", "drop_weapon"];
        public static enemyTypes: string[] = ["small_enemy", "mid_enemy", "big_enemy"];

        private ticks: number = 0;
        private removed: number = 0;

        public player:  Classes.Player   ;
        public enemys:  Classes.Enemy[]  ;
        public bullets: Classes.Bullet[] ;
        public drops:   Classes.Drop[]   ;

        constructor() {
            if (GameManager._init) { 
                throw new Error("GameManager Is An Instance.");
            }
        }

        public static getInstance(): GameManager {
            if (!GameManager._init) {
                GameManager._init = new GameManager();
            }
            return GameManager._init;
        }

        public startOrRestart() {
            this.createPlayer();
            this.enemys = [];
            this.bullets = [];
            this.drops  = [];
        }

        public onLoop(): void {

            this.player.onLoop();
            this.enemys.forEach(enemy => { enemy.onLoop(); });
            this.bullets.forEach(bullet => { bullet.onLoop(); });
            this.drops.forEach(drop => { drop.onLoop(); });

            let time = new Date().valueOf();
            this.ticks += 1;

            // Enemy Disapper & Drop Create
            for (let id = this.enemys.length - 1; id >= 0; id--) {
                let toRemove = false;

                if (this.enemys[id].y > Laya.stage.height + 200) {
                    toRemove = true;
                } else if (!this.enemys[id].isAlive()) {
                    toRemove = true;
                    if (this.enemys[id].type === "big_enemy") {
                        this.createDrop(this.enemys[id]);
                    }
                }

                if (toRemove) {
                    // Laya.stage.removeChild(this.enemys[id]);
                    this.enemys.splice(id, 1);
                    this.removed += 1;
                }
            }

            // Enemy Create
            if (this.ticks % 60 === 0) {
                // this.removed = this.removed <= 4 ? this.removed : 4;
                // let created = Math.min(12 - this.enemys.length, this.removed);
                // this.createEnemy(this.removed + 1);
                // this.removed = 0;
                GameManager.getInstance().createEnemy(2);
            }

            // Bullet Disapper
            for (let i = this.bullets.length - 1; i >= 0; i--) {
                if (this.bullets[i].y < -10 || !this.bullets[i].isAlive()) {
                    Laya.stage.removeChild(this.bullets[i]);
                    this.bullets.splice(i, 1);
                }
            }

            // Drop Disapper
            for (let j = this.drops.length - 1; j >= 0; j--) {
                if (new Date().valueOf() - this.drops[j].time > this.drops[j].lifeTime) {
                    Laya.stage.removeChild(this.drops[j]);
                    this.drops.splice(j, 1);
                }
            }
        }

        public pause() {}

        public resume() {}

        public stop() {}

        public createPlayer(): void {
            this.player = new Classes.Player();
            // Laya.stage.addChild(this.player);
            gameInstance.playerLayer.addChild(this.player);
        }

        public createEnemy(amount: number): void {
            for (let i = 0; i < amount; i++) {

                let r = Math.random();
                let type = r < 0.7 ? "small_enemy" : (r < 0.93 ? "mid_enemy" : "big_enemy");

                let enemy: Classes.Enemy = new Classes.Enemy();
                enemy.config(type);
                enemy.pos(Math.random() * 400 + 40, Math.random() * 200);
                
                this.enemys.push(enemy);
                // Laya.stage.addChild(enemy);
                gameInstance.enemyLayer.addChild(enemy);
            }
        }

        public createBullet(owner: Classes.Player): void {
 
            let odd = !!(owner.shootType % 2);
            let space = 18;

            for (let i = 0; i < owner.shootType; i++) {
                let bullet: Classes.Bullet = new Classes.Bullet(owner);

                let pos;

                if (i === 0) { pos = owner.x; } 
                else if (i % 2) { pos = owner.x - space * Math.ceil(i / 2); }
                else { pos = owner.x + space * Math.ceil(i / 2); }

                if (!odd) { pos += space / 2; }

                bullet.pos(pos, owner.y - owner.radius - 20);

                this.bullets.push(bullet);
                // Laya.stage.addChild(bullet);
                gameInstance.bulletLayer.addChild(bullet);
            }
        }

        public createDrop(creater: Classes.Enemy): void {
            let drop: Classes.Drop = new Classes.Drop();
                
            let type: string = Math.random() > 0.49 ? "drop_food" : "drop_weapon";
            drop.config(type);

            drop.pos(creater.x, creater.y);

            this.drops.push(drop);
            // Laya.stage.addChild(drop);
            gameInstance.dropLayer.addChild(drop);
        }

    }
}